﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Configuration;

namespace FiftyNine.Ag.AzureDevelopmentStorageProxy
{
    class DevStorageRequestHandler : RequestHandler
    {
        string BLOB_ADDRESS = ConfigurationManager.AppSettings["blobAddress"].ToLower();
        string TABLE_ADDRESS = ConfigurationManager.AppSettings["tableAddress"].ToLower();
        string QUEUE_ADRESS = ConfigurationManager.AppSettings["queueAddress"].ToLower();
        HttpListenerRequest _request;
        HttpListenerResponse _response;

        public DevStorageRequestHandler(HttpListenerRequest request, HttpListenerResponse response)
        {
            _request = request;
            _response = response;
            HandleRequest();
        }

        void HandleRequest()
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(GetMappedUrl());
            req.Method = _request.HttpMethod;
            req.Date = DateTime.UtcNow;
            foreach (var headerName in _request.Headers.AllKeys)
            {
                switch (headerName)
                {
                    case "Connection":
                    case "Host":
                    case "User-Agent":
                    case "Referer":
                    case "Accept":
                        break;
                    case "If-Modified-Since":
                        req.IfModifiedSince = DateTime.Parse(_request.Headers[headerName]);
                        break;
                    case "Content-Length":
                        req.ContentLength = long.Parse(_request.Headers[headerName]);
                        break;
                    case "Content-Type":
                        req.ContentType = _request.Headers[headerName];
                        break;
                    default:
                        req.Headers.Add(headerName, _request.Headers[headerName]);
                        break;
                }
            }
            if (_request.HttpMethod != "GET" && _request.HttpMethod != "HEAD")
            {
                req.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), req);
                return;
            }
            req.BeginGetResponse(new AsyncCallback(GetRequestResponseCallback), req);
        }
        void GetRequestStreamCallback(IAsyncResult iar)
        {
            HttpWebRequest req = (HttpWebRequest)iar.AsyncState;
            Stream requestStream = req.EndGetRequestStream(iar);
            _request.InputStream.CopyTo(requestStream);
            requestStream.Close();
            req.BeginGetResponse(new AsyncCallback(GetRequestResponseCallback), req);
        }
        void GetRequestResponseCallback(IAsyncResult iar)
        {
            HttpWebRequest req = (HttpWebRequest)iar.AsyncState;
            HttpWebResponse resp = null;
            try
            {
                resp = (HttpWebResponse)req.EndGetResponse(iar);
            }
            catch (WebException ex)
            {
                _response.StatusCode = (int)((HttpWebResponse)ex.Response).StatusCode;
                _response.OutputStream.Close();
                return;
            }

            foreach (var headerName in resp.Headers.AllKeys)
            {
                switch (headerName)
                {
                    case "Connection":
                    case "Host":
                    case "User-Agent":
                    case "Referer":
                    case "Transfer-Encoding":
                    case "Accept":
                        break;
                    case "Content-Length":
                        _response.ContentLength64 = resp.ContentLength;
                        break;
                    case "Content-Type":
                        _response.ContentType = resp.Headers[headerName];
                        break;
                    default:
                        _response.Headers[headerName] = resp.Headers[headerName];
                        break;
                }
            }
            Stream respStream = resp.GetResponseStream();
            respStream.CopyTo(_response.OutputStream);
            _response.OutputStream.Close();
        }

        string GetMappedUrl()
        {
            string url;
            if (_request.Url.AbsoluteUri.ToLower().StartsWith(BLOB_ADDRESS))
            {
                url = "http://127.0.0.1:10000/devstoreaccount1";
            }
            else if (_request.Url.AbsoluteUri.ToLower().StartsWith(QUEUE_ADRESS))
            {
                url = "http://127.0.0.1:10001/devstoreaccount1";
            }
            else
            {
                url = "http://127.0.0.1:10002/devstoreaccount1";
            }
            return url + _request.Url.PathAndQuery;
        }
    }
}
